package io

import (
	"fmt"
	"os"
	"path"
	"path/filepath"
	"strconv"
	"strings"
)

func PathExists(pathname string) bool {
	_, err := os.Stat(pathname)
	if err == nil {
		return true
	}
	if os.IsNotExist(err) {
		return false
	} else {
		println(err)
		//panic(err)
	}
	return false
}

func Create(name string, perm os.FileMode) (*os.File, error) {
	return OpenFile(name, os.O_RDWR|os.O_CREATE|os.O_TRUNC, perm)
}

func OpenFile(name string, flag int, perm os.FileMode) (*os.File, error) {
	err := os.MkdirAll(path.Dir(name), 0755)
	if err != nil {
		return nil, err
	}
	return os.OpenFile(name, flag, perm)
}

func IsDir(pathname string) bool {
	s, err := os.Stat(pathname)
	if err != nil {
		return false
	}
	return s.IsDir()
}

func IsFile(pathname string) bool {
	s, err := os.Stat(pathname)
	if err != nil {
		return false
	}
	return s.Mode().IsRegular()
}

func IsLink(pathname string) bool {
	s, err := os.Stat(pathname)
	if err != nil {
		return false
	}
	return s.Mode()&os.ModeSymlink != 0
}

func IsDevice(pathname string) bool {
	s, err := os.Stat(pathname)
	if err != nil {
		return false
	}
	return s.Mode()&os.ModeDevice != 0
}

func IsCharDevice(pathname string) bool {
	s, err := os.Stat(pathname)
	if err != nil {
		return false
	}
	return s.Mode()&os.ModeCharDevice != 0
}

func IsSocket(pathname string) bool {
	s, err := os.Stat(pathname)
	if err != nil {
		return false
	}
	return s.Mode()&os.ModeSocket != 0
}

func IsPipe(pathname string) bool {
	s, err := os.Stat(pathname)
	if err != nil {
		return false
	}
	return s.Mode()&os.ModeNamedPipe != 0
}

func IsFIFO(pathname string) bool {
	return IsPipe(pathname)
}

func PathCanCreate(pathname string) string {
	if PathExists(pathname) {
		dir, name := filepath.Split(pathname)
		names := strings.Split(name, ".")
		if len(names[0]) > 3 && names[0][len(names[0])-1] == ')' {
			b := strings.LastIndexByte(names[0], '(')
			if b > 0 {
				snum := names[0][b+1 : len(names[0])-1]
				num, err := strconv.Atoi(snum)
				if err == nil {
					num++
					names[0] = names[0][:b] + fmt.Sprintf("(%d)", num)
					return PathCanCreate(filepath.Join(dir, strings.Join(names, ".")))
				}
			}
		}
		names[0] += "(1)"
		return PathCanCreate(filepath.Join(dir, strings.Join(names, ".")))
	}
	return pathname
}
